/** Delegating controller class for the OntologyPlugin api
 * Use this class to interact with the api
 * The class is also a container for the different paths to property files
 */

package uhasselt.ontologyplugin;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class OntologyController 
{
    // holds the singleton OntologyController instance
	private static OntologyController _instance = null;
    	
	// factory that contains all OntologyReaders
	OntologyFactory _factory;
	// propertyreader used to read out the config file
	PropertyReader _reader;
	
	private OntologyController(String ontologiesPath, String ontologySettingsPath) 
	{
		// instantiated when buildFactory is called
		_factory = new OntologyFactory();
		_reader = new PropertyReader();
        this.buildFactory(ontologiesPath, ontologySettingsPath);
	}
    
    /**
     * If the OntologyController has not been created, an OntologyControllerException is thrown.
     * You should first call the initializeInstance(String, String) method.
     * @return the singleton OntologyController
     * @throws OntologyControllerException 
     */
    public static OntologyController instance() throws OntologyControllerException {
        if (_instance == null)
            throw new OntologyControllerException("The OntologyController has not been initialized.");
        return _instance;
    }
    
    /**
     * Initializes and returns an OntologyController. When the OntologyController has already been initialized, an
     * OntologyControllerException is thrown.
     * @param ontologiesPath path to the implementations of the different ontologies
     * @param ontologySettingsPath path to specific ontology settings
     * @return the singleton OntologyController
     * @throws OntologyControllerException 
     */
    public static synchronized OntologyController initializeInstance(String ontologiesPath, String ontologySettingsPath) throws OntologyControllerException{
        if (_instance != null)
            throw new OntologyControllerException("The OntologyController has already been initialized.");
        
        _instance = new OntologyController(ontologiesPath, ontologySettingsPath);
        return _instance;
    }

	
	/**
	 * Delegating function that returns a reader from the factory given a key
	 * @throws UnknownThesaurusException 
	 */
	public OntologyReader getReader(String key) throws UnknownThesaurusException
	{
		OntologyReader reader = _factory.getReader(key);
		if (reader == null)
			throw new UnknownThesaurusException("Thesaurus not defined in ontologies.properties");
		return _factory.getReader(key);
	}
	
	/**
	 * Constructs the UrlBased part of the factory
     * @param ontologiesPath path to the implementations of the different ontologies
     * @param ontologySettingsPath path to specific ontology settings
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	private void buildFactory(String ontologiesPath, String ontologySettingsPath)
	{
		// we are going to read from the ontologies.properties file
		_reader.setFile(ontologiesPath);
		// get all pairs from the ontologies file
		HashMap<String, String> propertyMap = _reader.getPairs();
		// run through all the pairs in the config and create all the readers
		for (Map.Entry<String, String> entry : propertyMap.entrySet()) {
			// e.g. agrovoc
		    String thesaurus = entry.getKey();
		    // e.g. uhasselt.ontologyplugin.UrlBasedReader
		    String implementation = entry.getValue();
		    // create a reader
			Class implClass = null;
			try {
				implClass = Class.forName(implementation);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			OntologyReader reader = null;
			try {
				reader = (OntologyReader) implClass.newInstance();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		    // let the reader initialise itself
			_reader.setFile(ontologySettingsPath);
		    reader.initialise(_reader, thesaurus);
		    // add it to the factory with as key the thesaurus
		    _factory.addReader(thesaurus, reader);
		}
	}


}
